package com.hspedu.tankgame4;

import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Vector;

/**
 * @author DL5O
 * @version 1.0
 * 坦克大战的绘图区域
 */
//为了监听事件需要实现 KeyListener
//为了让panel 不停的重绘子弹，需要将 MyPanel 实现一个Runnable 接口
public class MyPanel extends JPanel implements KeyListener, Runnable {
    //定义我的坦克
    private Hero hero = null;//玩家坦克
    //定义敌人的坦克
    Vector<EnemyTank> enemyTanks = new Vector<EnemyTank>();//用于存放敌人tank
    Vector<Node> nodes = null;//定义一个存放Node对象的Vector，用于恢复
    //说明，当子弹击中tank时，就加入一个Bomb对象到bombs中
    Vector<Bomb> bombs = new Vector<>();//定义一个Vector，用于存放炸弹

    int enemyTankSize = 6;//敌人坦克的数量
    boolean flag = true;

    //定义三张炸弹的图片，用于显示爆炸效果
    Image image1 = null;
    Image image2 = null;
    Image image3 = null;

    /**
     * 初始化MyPanel类，定义我方坦克，敌方坦克
     */
    public MyPanel(String key) {
        this.hero = new Hero(800, 250, 1, 20, 2);//初始化一个自己的Tank
        switch (key) {
            case "1":
                //初始化敌人的坦克
                for (int i = 0; i < enemyTankSize; i++) {
                    //enemyTanks.add(new EnemyTank(x, 100, 0, 5));
                    EnemyTank enemyTank = new EnemyTank((100 * (i + 1)), 0, 0, 1);
                    //设置坦克属性
                    enemyTank.setDirect(2);
            /*enemyTank.shot = new Shot(enemyTank.getX() + 20, enemyTank.getY() + 60,
                    enemyTank.getDirect(),enemyTank.getShotSpeed());//给该enemyTank加入一课子弹后面可以加入多个
            enemyTank.shots.add(enemyTank.shot);//加入到enemyTank 的 Vectors 对象
            new Thread(enemyTank.shot).start();//启动shot 对象
            //启动enemyTank线程*/
                    new Thread(enemyTank).start();
                    enemyTanks.add(enemyTank); //加入集合
                }
                EnemyTank.setEnemyTanks(enemyTanks);
                Recorder.setEnemyTanks(enemyTanks);
                //初始化
                image1 = Toolkit.getDefaultToolkit().getImage("src/bomb_1.gif");
                image2 = Toolkit.getDefaultToolkit().getImage("src/bomb_2.gif");
                image3 = Toolkit.getDefaultToolkit().getImage("src/bomb_3.gif");
                break;
            case "2"://继续上局游戏
                nodes = Recorder.getNodesAndEnemyTankRec();
                for (int i = 0; i < nodes.size(); i++) {
                    Node node = nodes.get(i);
                    EnemyTank enemyTank = new EnemyTank(node.getX(), node.getY(), 0, 1);
                    //设置坦克属性
                    enemyTank.setDirect(node.getDirect());
                    new Thread(enemyTank).start();
                    enemyTanks.add(enemyTank); //加入集合
                }
                EnemyTank.setEnemyTanks(enemyTanks);
                Recorder.setEnemyTanks(enemyTanks);
                //初始化
                image1 = Toolkit.getDefaultToolkit().getImage("src/bomb_1.gif");
                image2 = Toolkit.getDefaultToolkit().getImage("src/bomb_2.gif");
                image3 = Toolkit.getDefaultToolkit().getImage("src/bomb_3.gif");
                break;
            default:
                System.out.println("你的输入有误...");
        }

    }


    /**
     * 编写方法，判断我方的tank是否击中敌人的tank
     *
     * @param s    子弹对象
     * @param tank 敌人的tank(后面可以改)
     *             因为子弹的位置在不停的变换，故可以在发射子弹的时候判断，或者在重绘的时候判断即可
     */
    public void hitTank(Shot s, Tank tank) {
        //判断s 击中坦克
        if (tank == null) {
            return;
        }
        switch (tank.getDirect()) {
            case 0://向上
            case 2://向下
                if (s.x >= tank.getX() && s.x < tank.getX() + 40
                        && s.y >= tank.getY() && s.y <= tank.getY() + 60) {
                    s.isLive = false;
                    tank.isLive = false;
                    System.out.println("坦克被击中");
                    if (tank instanceof EnemyTank) {
                        enemyTanks.remove(tank);
                        Recorder.setAllEnemyTankNum(Recorder.getAllEnemyTankNum() + 1);
                    } else if (tank instanceof Hero) {
                        hero = null;
                    }
                    //创建一个bomb对象，加入到bombs集合中
                    Bomb bomb = new Bomb(tank.getX(), tank.getY());
                    bombs.add(bomb);
                }
                break;
            case 1:
            case 3://坦克向右向左
                if (s.x > tank.getX() && s.x < tank.getX() + 60
                        && s.y > tank.getY() && s.y < tank.getY() + 40) {
                    s.isLive = false;
                    tank.isLive = false;
                    System.out.println("坦克被击中");
                    if (tank instanceof EnemyTank) {
                        enemyTanks.remove(tank);
                        Recorder.setAllEnemyTankNum(Recorder.getAllEnemyTankNum() + 1);
                    } else if (tank instanceof Hero) {
                        hero = null;
                    }
                    Bomb bomb = new Bomb(tank.getX(), tank.getY());
                    bombs.add(bomb);
                }
                break;
        }
    }

    /**
     * 用于每次重绘时，判断子弹是否击中敌人
     * 把hero类中的shots集合依次遍历，然后依次和敌人坦克集合的每个坦克位置
     * 进行比较判断
     */
    public void hitEnemyTank() {
        //判断是否击中了敌人的tank
        for (int i = 0; i < hero.shots.size(); i++) {
            Shot shot = hero.shots.get(i);
            if (shot != null &&
                    shot.isLive) {//当前子弹是活着的
                //遍历所有的坦克
                for (int j = 0; j < enemyTanks.size(); j++) {
                    EnemyTank enemyTank = enemyTanks.get(j);
                    hitTank(shot, enemyTank);
                }
            }
        }
    }

    /**
     * 用于判断是敌人坦克否击中玩家坦克
     */
    public void hitHero() {
        for (int i = 0; i < enemyTanks.size(); i++) {
            //取出敌人的坦克
            EnemyTank enemyTank = enemyTanks.get(i);
            //取出敌人坦克的每一颗子弹
            if (!enemyTank.shots.isEmpty()) {
                for (int j = 0; j < enemyTank.shots.size(); j++) {
                    Shot shot = enemyTank.shots.get(j);
                    if (shot.isLive) {
                        hitTank(shot, hero);
                    }
                }
            }
        }
    }


    @Override
    public void keyTyped(KeyEvent e) {

    }

    //处理wasd键按下的键
    @Override
    public void keyPressed(KeyEvent e) {

        if (hero != null) {
            if (e.getKeyCode() == KeyEvent.VK_W) {//向上移动
                //改变坦克的方向
                hero.setDirect(0);
                if (hero.getY() > 0) {
                    hero.moveUp();
                }

            } else if (e.getKeyCode() == KeyEvent.VK_D) {//向右移动
                hero.setDirect(1);
                if (hero.getX() + 60 < 1000) {
                    hero.moveRight();
                }
            } else if (e.getKeyCode() == KeyEvent.VK_S) {//向下移动
                hero.setDirect(2);
                if (hero.getY() + 60 < 750) {
                    hero.moveDown();
                }
            } else if (e.getKeyCode() == KeyEvent.VK_A) {//想左移动
                hero.setDirect(3);
                if (hero.getX() > 0) {
                    hero.moveLeft();
                }
            }

            //当用户按下J键，就发射
            if (e.getKeyCode() == KeyEvent.VK_J) {
                System.out.println("按下J键,子弹开始射击");
            /*
                发射一颗子弹
                if (e.getKeyCode() == KeyEvent.VK_J) {
                System.out.println("按下J键,子弹开始射击");
                if(hero.shot == null || !(hero.shot.isLive)) {
                    //当hero的子弹对象为空
                    //或者hero子弹对象的生命周期为false时，才new 一个新的shot对象
                    hero.shotEnemy();
                }
            }
             */
            /*
            //控制坦克发射数量
            if(hero.shots.size() < 5){
                hero.shotEnemy();
            }*/
                //发射多颗子弹
                hero.shotTank();
            }
        }
        repaint();
    }

    @Override
    public void keyReleased(KeyEvent e) {

    }

    @Override
    public void paint(Graphics g) {
        super.paint(g);
        g.fillRect(0, 0, 1000, 750);//填充矩形，默认是黑色
        showInfo(g);
        //画出坦克-封装到方法
        //画出玩家的tank
        if (hero != null && hero.isLive) {
            drawTank(hero.getX(), hero.getY(), g, hero.getDirect(), hero.getType(), hero.isLive); //画出玩家的坦克
            drawShot(hero, g);//画出玩家坦克 打出的子弹
        }

        //画出敌人坦克
        if (enemyTanks.isEmpty()) {
            if (flag == true) {
                System.out.println("敌人全部暴毙，任务完成...");
                flag = false;
            }
        } else {
            //改用for循环
            for (int i = 0; i < enemyTanks.size(); i++) {
                EnemyTank enemyTank = enemyTanks.get(i);
                if (enemyTank.isLive) {//如果敌人的tank存活，那么就进行绘制，绘制敌人的子弹和tank
                    drawTank(enemyTank.getX(), enemyTank.getY(), g, enemyTank.getDirect(),
                            enemyTank.getType(), enemyTank.isLive); //绘制tank
                    drawShot(enemyTank, g);
                } else {
                    enemyTanks.remove(enemyTank);
                }
            }
        }

        //如果bombs 集合中有对象，就画出
        for (int i = 0; i < bombs.size(); i++) {
            //取出炸弹
            Bomb bomb = bombs.get(i);
            //根据当前这个bomb对象的life值去画出对应的图片
            if (bomb.life > 6) {
                g.drawImage(image1, bomb.x, bomb.y, 60, 60, this);
            } else if (bomb.life > 3) {
                g.drawImage(image2, bomb.x, bomb.y, 60, 60, this);
            } else {
                g.drawImage(image3, bomb.x, bomb.y, 60, 60, this);
            }
            //让给炸弹的生命值减少
            bomb.lifeDown();
            if (bomb.life == 0) {
                bombs.remove(bomb);
            }
        }
    }


    /**
     * 编写方法，画出坦克
     *
     * @param x      坦克的x坐标
     * @param y      坦克的y坐标
     * @param g      画笔
     * @param direct 坦克的方向
     * @param type   坦克的类型 0代表敌人的坦克，1代表玩家的坦克
     */
    public void drawTank(int x, int y, Graphics g, int direct, int type, boolean isLive) {

        //根据不同的坦克类型，设置不同的颜色
        switch (type) {
            case 0://敌人的tank
                g.setColor(Color.cyan);
                break;
            case 1:
                g.setColor(Color.yellow);
                break;
        }

        //根据坦克的方向来绘制对应形状的tank
        //direct 表示方向，分别用(0 向上 1向右 2向下 3向左)
        switch (direct) {
            case 0://向上的
                g.fill3DRect(x, y, 10, 60, false);//画出左边的轮子
                g.fill3DRect(x + 10, y + 10, 20, 40, false);//中间的矩形
                g.fillOval(x + 10, y + 20, 20, 20);//坦克轮盘
                g.drawLine(x + 20, y + 30, x + 20, y);//坦克的炮筒
                g.fill3DRect(x + 30, y, 10, 60, false);//画出右边的矩形
                break;
            case 1://向右边的
                g.fill3DRect(x, y, 60, 10, false);//画出左边的轮子
                g.fill3DRect(x + 10, y + 10, 40, 20, false);//中间的矩形
                g.fillOval(x + 20, y + 10, 20, 20);//坦克轮盘
                g.drawLine(x + 30, y + 20, x + 60, y + 20);//坦克的炮筒
                g.fill3DRect(x, y + 30, 60, 10, false);//画出右边的矩形
                break;
            case 2://向下
                g.fill3DRect(x, y, 10, 60, false);//画出左边的轮子
                g.fill3DRect(x + 10, y + 10, 20, 40, false);//中间的矩形
                g.fillOval(x + 10, y + 20, 20, 20);//坦克轮盘
                g.drawLine(x + 20, y + 30, x + 20, y + 60);//坦克的炮筒
                g.fill3DRect(x + 30, y, 10, 60, false);//画出右边的矩形
                break;
            case 3://向左
                g.fill3DRect(x, y, 60, 10, false);//画出左边的轮子
                g.fill3DRect(x + 10, y + 10, 40, 20, false);//中间的矩形
                g.fillOval(x + 20, y + 10, 20, 20);//坦克轮盘
                g.drawLine(x + 30, y + 20, x, y + 20);//坦克的炮筒
                g.fill3DRect(x, y + 30, 60, 10, false);//画出右边的矩形
                break;
            default:
                System.out.println("暂时没有处理");
        }
    }

    /**
     * 编写方法 画出坦克射出的子弹
     *
     * @param tank Tank接口，实现了Tank接口的类
     * @param g    画笔工具
     */
    public void drawShot(Tank tank, Graphics g) {
        //玩家的坦克
        if (tank instanceof Hero) {
            Hero hero = (Hero) tank;
            //可以抽象出去,发射一颗子弹
            /*if (hero.shot != null && hero.shot.isLive == true) {
                System.out.println("子弹被绘制...");
                g.setColor(Color.yellow);
                g.draw3DRect(hero.shot.x, hero.shot.y, 2, 2, false);
                return true;
            }*/

            //将hero子弹集合 shots，遍历取出绘制
            for (int i = 0; i < hero.shots.size(); i++) {
                Shot shot = hero.shots.get(i);
                if (shot != null && shot.isLive) {
                    //System.out.println("子弹被绘制...");
                    g.setColor(Color.yellow);
                    g.draw3DRect(shot.x, shot.y, 2, 2, false);
                } else {
                    hero.shots.remove(shot);
                }
            }
        }

        //敌人的坦克
        if (tank instanceof EnemyTank) {
            EnemyTank enemyTank = (EnemyTank) tank;//向下转型
            //取出子弹
            for (int i = 0; i < enemyTank.shots.size(); i++) {
                Shot shot = enemyTank.shots.get(i);
                if (shot.isLive) {//isLive == true的时候
                    //System.out.println("敌人tank的子弹被绘制");
                    g.draw3DRect(shot.x, shot.y, 2, 2, false);
                } else {
                    //从vector 移除
                    enemyTank.shots.remove(shot);
                }
            }
        }
    }

    /**
     * 画出玩家的总成绩
     *
     * @param g
     */
    public void showInfo(Graphics g) {
        g.setColor(Color.BLACK);
        Font font = new Font("宋体", Font.BOLD, 25);
        g.setFont(font);
        g.drawString("您累计击败坦克的数量", 1020, 30);
        drawTank(1020, 60, g, 0, 0, true);
        g.setColor(Color.BLACK);
        g.drawString(Recorder.getAllEnemyTankNum() + "", 1080, 100);
    }

    @Override
    public void run() {
        //每隔100毫秒，重绘这个区域
        while (true) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if (hero != null && hero.isLive) {
                hitEnemyTank();
            }
            if (!enemyTanks.isEmpty()) {
                hitHero();
            }
            this.repaint();
        }
    }
}
